Dash App in Quarto

import pandas as pd
import altair as alt 
import warnings
import geopandas as gpd
import json
import urllib.request

df = pd.read_csv('security_incidents.csv')
df.head()
Incident ID Year Month Day Country Code Country Region District City UN ... Attack context Location Latitude Longitude Motive Actor type Actor name Details Verified Source
0 1 1997 1.0 NaN KH Cambodia Banteay Meanchey NaN NaN 0 ... Unknown Unknown 14.070929 103.099916 Unknown Unknown Unknown 1 ICRC national staff killed while working in ... Archived Archived
1 2 1997 1.0 NaN RW Rwanda Northern Musanze Ruhengeri 0 ... Raid Office/compound -1.499840 29.634970 Unknown Unknown Unknown 3 INGO international (Spanish) staff killed, 1... Archived Archived
2 3 1997 2.0 NaN TJ Tajikistan NaN NaN NaN 4 ... Unknown Unknown 38.628173 70.815654 NaN Unknown Unknown 3 UN national staff, 1 UN international (Niger... Archived Archived
3 4 1997 2.0 NaN SO Somalia Lower Juba Kismayo Kismayo 0 ... Unknown Unknown -0.358216 42.545087 Political Non-state armed group: Regional Al-Itihaad al-Islamiya 1 INGO international staff killed by Al ittiha... Archived Archived
4 5 1997 2.0 14.0 RW Rwanda Kigali Kigali Kigali 1 ... Individual attack Unknown -1.950851 30.061508 Political Unknown Unknown 1 UN national staff shot and killed in Kigali ... Archived Archived

5 rows × 41 columns

from vega_datasets import data

countries = alt.topo_feature(data.world_110m.url, "countries")

selection = alt.selection_interval()

base_map = alt.Chart(countries).mark_geoshape(
    fill='lightgray', stroke='white'
).project(
    'equirectangular' 
).properties(
    width=600, height=450
)
df = df.dropna(subset=['Country'])


df['Year'] = df['Year'].astype(int)

year_dropdown = alt.param(
    name="Year", 
    bind=alt.binding_select(options=sorted(df['Year'].unique())), 
    value=df['Year'].min()
)

points = alt.Chart(df).mark_circle().encode(
    longitude='Longitude:Q',
    latitude='Latitude:Q',
    size=alt.Size('Total killed:Q', scale=alt.Scale(range=[10, 300])),  
    color=alt.Color('Attack context:N', scale=alt.Scale(scheme='category10')), 
    tooltip=['Year:N', 'Country:N', 'Total killed:Q','Total affected:Q', 'Attack context:N']
).transform_filter(alt.datum.Year == year_dropdown
)

alt.layer(base_map, points).add_params(year_dropdown)
grouped_df = df.groupby('Country')['Total affected'].sum().reset_index()
grouped_df = grouped_df.sort_values(by='Total affected', ascending=False)
grouped_df.head(10)
Country Total affected
0 Afghanistan 1354
76 South Sudan 891
78 Sudan 667
80 Syrian Arab Republic 608
74 Somalia 585
64 Occupied Palestinian Territories 579
21 DR Congo 448
53 Mali 264
65 Pakistan 259
14 Central African Republic 246
import dash
from dash import dcc, html
from dash.dependencies import Input, Output, State
import plotly.express as px
from jupyter_dash import JupyterDash

bar_chart = px.bar(grouped_df.head(6), x='Country', y='Total affected', title="Total Affected by Country")

scatter_plot = px.scatter(df, x='Year', y='Total affected', color='Country', title="Scatter Plot of Total Affected over Time")
app = JupyterDash(__name__)

app.layout = html.Div([
    html.H1("Interactive Plot Example"),
    html.Div([
        # The bar chart
        dcc.Graph(id='bar-chart', figure=bar_chart),
    ], style={'width': '48%', 'display': 'inline-block'}),
    
    html.Div([
        # The scatter plot
        dcc.Graph(id='scatter-plot', figure=None),
    ], style={'width': '48%', 'display': 'inline-block'}),
    
    # Reset button
    html.Button("Reset", id="reset-button", n_clicks=0),
])

@app.callback(
    Output('scatter-plot', 'figure'),
    [Input('bar-chart', 'clickData'),
     Input('reset-button', 'n_clicks')])

def update_scatter_plot(clickData,n_clicks):

    if n_clicks > 0:
        return scatter_plot

    if clickData is not None:
        selected_country = clickData['points'][0]['x']
        filtered_df = df[df['Country'] == selected_country]

        updated_scatter_plot = px.scatter(filtered_df, x='Year', y='Total affected', color='Country', title=f"Scatter Plot for {selected_country}")
        return updated_scatter_plot

    return scatter_plot

app.run_server(debug=True,port=8055,use_reloader=False, mode='inline')